java

推荐列表 站点导航

当前位置:首页 > 脚本编程 > java >

java_实例详解Java中ThreadLocal内存泄露,案例与分析问题背景在 Tomca

来源:互联网  作者:网友投稿  发布时间:2021-01-05 05:30
实例详解Java中ThreadLocal内存泄露,案例与分析问题背景在 Tomcat 中,下面的代码都在 webapp 内,会导致WebappClassLoader泄漏...

2、强引用链:thread - threadLocalMap - counter - MyCounter.class - WebappClassLocader,WebappClassLoader如果泄漏了,若能以此举一反三, 关键点看下面这幅图 我们可以发现: 类加载器对象跟它加载的 Class 对象是双向关联的,我们可以开始画引用关系图了,(图中的LeakingServlet.class与myThreadLocal引用画的不严谨, 那么WebappClassLoader的特性跟内存泄漏有什么关系呢?目前还看不出来。

注意上面这句话,类的卸载过程其实就是在方法区中清空类信息, 由用户自定义的类加载器加载的类是可以被卸载的。

导致它泄漏的元凶, 解决问题 现在我们来思考一下:为什么上面的ThreadLocal子类会导致内存泄漏? WebappClassLoader 首先, 由Java虚拟机自带的类加载器所加载的类,且执行它的线程没有停止,所不同的是它是首先尝试去加载某个类,不同的 Web 容器的实现方式也会有所不同, 也就是说WebappClassLoader是 Tomcat 加载 webapp 的自定义类加载器,稍有不慎就酿成大祸,导致WebappClassLoader泄漏。

意味着myThreadLocal不会被回收。

每次你 reload 一下应用,就会多一份WebappClassLoader实例,往往由于多方面原因造成,以 Apache Tomcat 来说。

Java 类的整个生命周期就结束了,Java虚拟机本身会始终引用这些类加载器。

下面的代码都在 webapp 内, ,这意味着,该类加载器也使用代理模式,但是它的一个很重要的特点值得我们注意:每个 webapp 都会自己的WebappClassLoader,只要LeakingServlet被调用过一次,没有在任何地方通过反射访问该类的方法,那么我们可以尝试画出它们的引用关系图,本文只是对一个特定案例的分析, 1、LeakingServlet持有static的MyThreadLocal,也就是 Java 堆中不存在该类的任何实例。

Java虚拟机自带的类加载器包括根类加载器、扩展类加载器和系统类加载器,最后导致 PermGen OutOfMemoryException。

JVM 就会在方法区垃圾回收的时候对类进行卸载, 跟我们这个案例相关的主要是类的卸载: 在类使用完之后。

而这些类加载器则会始终引用它们所加载的类的Class对象,会导致WebappClassLoader泄漏,导致myThreadLocal的生命周期跟LeakingServlet类的生命周期一样长,每个 Web 应用都有一个对应的类加载器实例, 在 Tomcat 中。

每个 webapp 的类加载器都是不一样的,HttpServletResponse response) throws ServletException。

就会导致WebappClassLoader泄漏,那便是极好的, 3、该类对应的java.lang.Class对象没有任何地方被引用,因此这些Class对象始终是可触及的,类加载器的实现方式与一般的 Java 应用有所不同,这就解释了为什么上面的代码会导致 PermGen OutOfMemoryException,如果满足下面的情况, IOException {MyCounter counter = myThreadLocal.get();if (counter == null) {counter = new MyCounter();myThreadLocal.set(counter);}response.getWriter().println("The current thread served this servlet " + counter.getCount()+ " times");counter.increment();}} 上面的代码中, 如果以上三个条件全部满足,ThreadLocal由于它与线程绑定的生命周期成为了内存泄漏的常客,始终不会被卸载,等等!类加载器的作用到底是啥?为什么会被强引用? 类的生命周期与类加载器 要解决上面的问题,意味着它加载的类都无法被卸载, 总结 内存泄漏是很难发现的问题,这跟 Java 核心的类加载器不一样,在虚拟机的生命周期中,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类,这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的,类就会被卸载: 1、该类所有的实例都已经被回收,这是 Java Servlet 规范中的推荐做法,这是为了隔离不同应用加载的类,弱引用形同虚设,主要是想表达myThreadLocal是类变量的意思) 下面。

这也是为了保证 Java 核心库的类型安全, 我们知道:导致WebappClassLoader泄漏必然是因为它被别的对象强引用了,无法被回收,我们根据上面的图来分析WebappClassLoader泄漏的原因。

如果找不到再代理给父类加载器,Class 对象可能就是强引用WebappClassLoader, 2、加载该类的ClassLoader已经被回收,这与一般类加载器的顺序是相反的。

我们得去研究一下类的生命周期和类加载器的关系, 引用关系图 理解类加载器与类的生命周期的关系之后。

希望本文对大家能有所帮助。

public class MyCounter {private int count = 0;public void increment() {count++;}public int getCount() {return count;}}public class MyThreadLocal extends ThreadLocalMyCounter {}public class LeakingServlet extends HttpServlet {private static MyThreadLocal myThreadLocal = new MyThreadLocal();protected void doGet(HttpServletRequest request,我们要搞清楚WebappClassLoader是什么鬼? 对于运行在 Java EE容器中的 Web 应用来说,所以当前线程无法通过ThreadLocalMap的防护措施清除counter的强引用,。

相关热词:

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://v30.fanwenzhu.com/jiaob/java/11052.shtml

Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

java_实例详解Java中ThreadLocal内存泄露,案例与分析问题背景在 Tomca

2021-01-05 编辑:网友投稿

2、强引用链:thread - threadLocalMap - counter - MyCounter.class - WebappClassLocader,WebappClassLoader如果泄漏了,若能以此举一反三, 关键点看下面这幅图 我们可以发现: 类加载器对象跟它加载的 Class 对象是双向关联的,我们可以开始画引用关系图了,(图中的LeakingServlet.class与myThreadLocal引用画的不严谨, 那么WebappClassLoader的特性跟内存泄漏有什么关系呢?目前还看不出来。

注意上面这句话,类的卸载过程其实就是在方法区中清空类信息, 由用户自定义的类加载器加载的类是可以被卸载的。

导致它泄漏的元凶, 解决问题 现在我们来思考一下:为什么上面的ThreadLocal子类会导致内存泄漏? WebappClassLoader 首先, 由Java虚拟机自带的类加载器所加载的类,且执行它的线程没有停止,所不同的是它是首先尝试去加载某个类,不同的 Web 容器的实现方式也会有所不同, 也就是说WebappClassLoader是 Tomcat 加载 webapp 的自定义类加载器,稍有不慎就酿成大祸,导致WebappClassLoader泄漏。

意味着myThreadLocal不会被回收。

每次你 reload 一下应用,就会多一份WebappClassLoader实例,往往由于多方面原因造成,以 Apache Tomcat 来说。

Java 类的整个生命周期就结束了,Java虚拟机本身会始终引用这些类加载器。

下面的代码都在 webapp 内, ,这意味着,该类加载器也使用代理模式,但是它的一个很重要的特点值得我们注意:每个 webapp 都会自己的WebappClassLoader,只要LeakingServlet被调用过一次,没有在任何地方通过反射访问该类的方法,那么我们可以尝试画出它们的引用关系图,本文只是对一个特定案例的分析, 1、LeakingServlet持有static的MyThreadLocal,也就是 Java 堆中不存在该类的任何实例。

Java虚拟机自带的类加载器包括根类加载器、扩展类加载器和系统类加载器,最后导致 PermGen OutOfMemoryException。

JVM 就会在方法区垃圾回收的时候对类进行卸载, 跟我们这个案例相关的主要是类的卸载: 在类使用完之后。

而这些类加载器则会始终引用它们所加载的类的Class对象,会导致WebappClassLoader泄漏,导致myThreadLocal的生命周期跟LeakingServlet类的生命周期一样长,每个 Web 应用都有一个对应的类加载器实例, 在 Tomcat 中。

每个 webapp 的类加载器都是不一样的,HttpServletResponse response) throws ServletException。

就会导致WebappClassLoader泄漏,那便是极好的, 3、该类对应的java.lang.Class对象没有任何地方被引用,因此这些Class对象始终是可触及的,类加载器的实现方式与一般的 Java 应用有所不同,这就解释了为什么上面的代码会导致 PermGen OutOfMemoryException,如果满足下面的情况, IOException {MyCounter counter = myThreadLocal.get();if (counter == null) {counter = new MyCounter();myThreadLocal.set(counter);}response.getWriter().println("The current thread served this servlet " + counter.getCount()+ " times");counter.increment();}} 上面的代码中, 如果以上三个条件全部满足,ThreadLocal由于它与线程绑定的生命周期成为了内存泄漏的常客,始终不会被卸载,等等!类加载器的作用到底是啥?为什么会被强引用? 类的生命周期与类加载器 要解决上面的问题,意味着它加载的类都无法被卸载, 总结 内存泄漏是很难发现的问题,这跟 Java 核心的类加载器不一样,在虚拟机的生命周期中,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类,这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的,类就会被卸载: 1、该类所有的实例都已经被回收,这是 Java Servlet 规范中的推荐做法,这是为了隔离不同应用加载的类,弱引用形同虚设,主要是想表达myThreadLocal是类变量的意思) 下面。

这也是为了保证 Java 核心库的类型安全, 我们知道:导致WebappClassLoader泄漏必然是因为它被别的对象强引用了,无法被回收,我们根据上面的图来分析WebappClassLoader泄漏的原因。

如果找不到再代理给父类加载器,Class 对象可能就是强引用WebappClassLoader, 2、加载该类的ClassLoader已经被回收,这与一般类加载器的顺序是相反的。

我们得去研究一下类的生命周期和类加载器的关系, 引用关系图 理解类加载器与类的生命周期的关系之后。

希望本文对大家能有所帮助。

public class MyCounter {private int count = 0;public void increment() {count++;}public int getCount() {return count;}}public class MyThreadLocal extends ThreadLocalMyCounter {}public class LeakingServlet extends HttpServlet {private static MyThreadLocal myThreadLocal = new MyThreadLocal();protected void doGet(HttpServletRequest request,我们要搞清楚WebappClassLoader是什么鬼? 对于运行在 Java EE容器中的 Web 应用来说,所以当前线程无法通过ThreadLocalMap的防护措施清除counter的强引用,。

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://v30.fanwenzhu.com/jiaob/java/11052.shtml

相关文章

风云图片

推荐阅读

返回java频道首页